/*
 * Ork: a small object-oriented OpenGL Rendering Kernel.
 * Website : http://ork.gforge.inria.fr/
 * Copyright (c) 2008-2015 INRIA - LJK (CNRS - Grenoble University)
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, 
 * this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 * 
 * 3. Neither the name of the copyright holder nor the names of its contributors 
 * may be used to endorse or promote products derived from this software without 
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/*
 * Ork is distributed under the BSD3 Licence. 
 * For any assistance, feedback and remarks, you can check out the 
 * mailing list on the project page : 
 * http://ork.gforge.inria.fr/
 */
/*
 * Main authors: Eric Bruneton, Antoine Begault, Guillaume Piolat.
 */

#ifndef _ORK_COMPILED_RESOURCE_LOADER_H_
#define _ORK_COMPILED_RESOURCE_LOADER_H_

#include <map>

#include "ork/resource/ResourceLoader.h"

namespace ork
{

/**
 * A ResourceLoader that can load resources from the files produced by a
 * ResourceCompiler. This class is intended to be subclassed in order to
 * include the source code generated by a ResourceCompiler:
 \code
class MyResourceLoader : public CompiledResourceLoader
{
public:
    MyResourceLoader(const std::string &resourceDataFile) :
        CompiledResourceLoader(resourceDataFile)
    {
#include "resourceFile"
    }
};
\endcode
 * This source code will construct the %resource descriptors of the
 * resources that will be loaded by this loader, during the creation of
 * this loader.
 *
 * @ingroup resource
 */
class CompiledResourceLoader : public ResourceLoader
{
public:
    /*
     * A ResourceDescriptor that never delete its data part.
     */
    class StaticResourceDescriptor : public ResourceDescriptor
    {
    public:
        /**
         * Creates a new StaticResourceDescriptor.
         *
         * @param descriptor the XML part of this %resource descriptor.
         * @param data the ASCII of binary data part of the descriptor.
         * @param size the size of the ASCII or binary part in bytes.
         */
        StaticResourceDescriptor(const TiXmlElement *descriptor, unsigned char *data, unsigned int size);

        /**
         * Deletes this StaticResourceDescriptor.
         */
        virtual ~StaticResourceDescriptor();

        /**
         * Does nothing, i.e., do not delete the data of this descriptor.
         */
        virtual void clearData();
    };

    /**
     * Creates a new CompiledResourceLoader.
     *
     * @param resourceDataFile a file containing the data parts of the
     *      resources that must be loaded by this loader. This file
     *      must have been produced by a ResourceCompiler.
     */
    CompiledResourceLoader(const std::string &resourceDataFile);

    /**
     * Deletes this CompiledResourceLoader.
     */
    virtual ~CompiledResourceLoader();

    /**
     * Returns the path of the resource of the given name. This method
     * looks for paths stored in the #paths map, initialized during the
     * construction of this loader.
     *
     * @param name the name of a resource.
     * @return the path of this resource.
     * @throw exception if the resource is not found.
     */
    virtual std::string findResource(const std::string &name);

    /**
     * Loads the ResourceDescriptor of the given name. This method looks for
     * %resource descriptors stored in the #resources map, initialized
     * during the construction of this loader.
     *
     * @param name the name of the ResourceDescriptor to be loaded.
     * @return the ResourceDescriptor of the given name, or NULL if the %resource
     *      is not found.
     */
    virtual ptr<ResourceDescriptor> loadResource(const std::string &name);

    /**
     * Reloads the ResourceDescriptor of the given name. This method always
     * return NULL as the resources managed by this loader can not change.
     *
     * @param name the name of the ResourceDescriptor to be loaded.
     * @param currentValue the current value of this ResourceDescriptor.
     * @return the new value of this ResourceDescriptor, or NULL if this value
     *      has not changed.
     */
    virtual ptr<ResourceDescriptor> reloadResource(const std::string &name, ptr<ResourceDescriptor> currentValue);

protected:
    /**
     * The data parts of the resources that can be loaded by this loader.
     */
    unsigned char* data;

    /**
     * The paths that can be returned by #findResource.
     */
    std::map<std::string, std::string> paths;

    /**
     * The %resource descriptors that can be returned by #loadResource.
     */
    std::map< std::string, ptr<ResourceDescriptor> > resources;

    /**
     * Adds a %resource path to #paths. This method is called by the code
     * generated by ResourceCompiler.
     */
    void addPath(const std::string &name, const std::string &path);

    /**
     * Adds a %resource descriptor to #resources. This method is called by
     * the code generated by ResourceCompiler.
     */
    void addResource(const std::string &name, ptr<ResourceDescriptor> desc);
};

}

#endif
